package gwtappcontainer.server.apps.security;

import static gwtappcontainer.server.apps.security.OfyService.ofy;
import gwtappcontainer.server.DatastoreNamespaces;
import gwtappcontainer.server.apps.APIException;
import gwtappcontainer.shared.apis.APIResponse.Status;
import gwtappcontainer.shared.apps.security.RoleProp;
import gwtappcontainer.shared.apps.security.UserProp;

import java.util.List;
import java.util.TreeSet;

import com.google.appengine.api.NamespaceManager;


public class RoleRepository {	
	
	private final static String NAMESPACE = DatastoreNamespaces.SECURITY;
	
	static TreeSet<RoleProp> getAllRoles() {
		NamespaceManager.set(NAMESPACE);
		
		List<RoleEntity> all = ofy().load().type(RoleEntity.class).list();								
		
		TreeSet<RoleProp> props = new TreeSet<RoleProp>();
		
		for (RoleEntity entity : all) {
			props.add(entity.toProp());
		}				
		
		return props;
	}
	
	static void addRole(String role, String login) {
		
		AccessController.ensurePrivilege(login, Privileges.EDIT_ROLE);
		role = role.toUpperCase();
		RoleEntity entity = ofy().load().type(RoleEntity.class).
				filter("role", role).first().get();
		
		if (null != entity) 
			throw new APIException(Status.ERROR_RESOURCE_ALREADY_EXISTS, 
					"Role [" + role + "] already exists");
		
		entity = new RoleEntity();
		entity.role = role;
		
		ofy().save().entity(entity).now();				
	}
	
	static void deleteRole(String role, String login) {
		
		AccessController.ensurePrivilege(login, Privileges.EDIT_ROLE);
		role = role.toUpperCase();
		RoleEntity entity = ofy().load().type(RoleEntity.class).
				filter("role", role).first().get();
		
		if (null == entity)
			throw new APIException(Status.ERROR_RESOURCE_DOES_NOT_EXIST, 
					"Role [" + role + "] does not exist");
		
		TreeSet<UserProp> allUserProps = UserRepository.getAllUsers();
		
		//ensure no user is assigned this role		
		String usersWithRole = "";
		for (UserProp userProp : allUserProps) {
			if (userProp.roles.contains(role))
				usersWithRole += userProp.email + ", ";
		}
		
		if (! usersWithRole.equals(""))
			throw new APIException(Status.ERROR_RESOURCE_ALREADY_EXISTS, 
					"Following users have the role [" + role + "] assigned - " +
					usersWithRole + ". Please remove the role from these users first");
		
		ofy().delete().entity(entity).now();		
	}
	
	static void assignPrivilageToRole(String role, String privilege, String login) {
		AccessController.ensurePrivilege(login, Privileges.EDIT_ROLE);
		
		role = role.toUpperCase();
		privilege = privilege.toUpperCase();
		RoleEntity entity = ofy().load().type(RoleEntity.class).
				filter("role", role).first().get();
		
		if (null == entity)
			throw new APIException(Status.ERROR_RESOURCE_DOES_NOT_EXIST, 
					"Role [" + role + "] does not exist");
		
		if (! PrivilegeRepository.getAllPrivileges().contains(privilege))
			throw new APIException(Status.ERROR_RESOURCE_DOES_NOT_EXIST, 
					"Privilege [" + privilege + "] is not valid");			
		
		entity.privileges.add(privilege);
		ofy().save().entity(entity).now();
	}
	
	static void unassignPrivilageToRole(String role, String privilege, String login) {
		AccessController.ensurePrivilege(login, Privileges.EDIT_ROLE);
		role = role.toUpperCase();
		privilege = privilege.toUpperCase();
		RoleEntity entity = ofy().load().type(RoleEntity.class).
				filter("role", role).first().get();
		
		if (null == entity)
			throw new APIException(Status.ERROR_RESOURCE_DOES_NOT_EXIST, 
					"Role [" + role + "] does not exist");
		
		if (! PrivilegeRepository.getAllPrivileges().contains(privilege))
			throw new APIException(Status.ERROR_RESOURCE_DOES_NOT_EXIST, 
					"Privilege [" + privilege + "] is not valid");				
		
		entity.privileges.remove(privilege);
		ofy().save().entity(entity).now();
	}		
}
